package com.wctj.api.business.huifu.service.impl;

import com.wctj.api.base.Result;
import com.wctj.api.base.constant.Constants;
import com.wctj.api.base.entity.DdwxCorpMemberInfo;
import com.wctj.api.base.entity.DdwxPaymentRecord;
import com.wctj.api.base.entity.DdwxPersonalMemberInfo;
import com.wctj.api.base.enums.ApiCode;
import com.wctj.api.base.enums.PayPlatformEnums;
import com.wctj.api.base.exception.CustomException;
import com.wctj.api.base.utils.InstanceConvertUtil;
import com.wctj.api.base.utils.JsonUtils;
import com.wctj.api.base.utils.OrderIdUtils;
import com.wctj.api.business.common.dto.DdwxPaymentMessageInfoDTO;
import com.wctj.api.business.common.dto.PayOrderDTO;
import com.wctj.api.business.common.dto.PaymentIdDTO;
import com.wctj.api.business.common.service.AbstractPayManagerService;
import com.wctj.api.business.huifu.dto.HuiFuCorpMemberUserDTO;
import com.wctj.api.business.huifu.dto.HuiFuMemberUserDTO;
import com.wctj.api.business.huifu.dto.HuiFuQueryMemberUserDTO;
import com.wctj.api.business.huifu.enums.HuiFuPayStatusEnums;
import com.wctj.api.business.huifu.service.HuiFuPayManagerService;
import com.wctj.api.infra.common.bean.PayOrder;
import com.wctj.api.infra.huifu.api.HuiFuPayConfigStorage;
import com.wctj.api.infra.huifu.api.HuiFuPayService;
import com.wctj.api.infra.huifu.dto.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
public class HuiFuPayManagerServiceImpl extends AbstractPayManagerService implements HuiFuPayManagerService {
    @Value("${paysystem.pay.notifyUrl}")
    private String notifyUrl;
    @Value("${paysystem.pay.filePath:/logs/file/}")
    private String filePath;
    @Resource
    private HuiFuPayService huiFuPayService;


    @Override
    public Result toPay(PayOrderDTO param, String payOrderNum) {
        // 组装参数
        String payChanel = param.getPayChannel().getCode();
        String openId = param.getOpenId();
        HuiFuPayConfigStorage config = new HuiFuPayConfigStorage();
        config.setApiKey(param.getApiKey());
        config.setAppId(param.getAppId());
        config.setMockApiKey("");
        config.setKeyPrivate(param.getKeyPrivate());
        config.setPayChannel(payChanel);
        config.setNotifyUrl(notifyUrl.replace("{payMode}", param.getPayChannel().getType().name()));

        //支付订单基础信息
        PayOrder payOrder = new PayOrder(param.getTitle()
                , StringUtils.isBlank(param.getDescription()) ? param.getTitle() : param.getDescription()
                , param.getPrice(), payOrderNum, openId);
        // 调用汇付天下 adapay 支付SDK
        HuiFuResponsePayInfo payInfo = huiFuPayService.toPay(config, payOrder);
        // 结果校验
        if (HuiFuPayStatusEnums.succeeded.name().equalsIgnoreCase(payInfo.getStatus())) {
            // 支付信息存储
            savePaymentInfo(param, payInfo, payOrderNum);
            return Result.success(payInfo);
        } else {
            return Result.fail(ApiCode.HUIFU_PAYMENT_ORDER_FAIL, payInfo.getErrorMsg());
        }
    }

    @Transactional(rollbackFor = {Exception.class})
    public void savePaymentInfo(PayOrderDTO param, HuiFuResponsePayInfo payInfo, String payOrderNum) {
        DdwxPaymentRecord paymentRecord = new DdwxPaymentRecord();
        paymentRecord.setBizCode(param.getBizCode());
        paymentRecord.setBizOrderNum(param.getBizOrderNum());
        paymentRecord.setPayChannel(param.getPayChannel().getCode());
        paymentRecord.setPayOrderNum(payOrderNum);
        paymentRecord.setPayNum(payInfo.getId());
        paymentRecord.setAppId(param.getAppId());
        paymentRecord.setMoney(param.getPrice());
        paymentRecord.setPlatform(param.getPayChannel().getType().name());
        // 处理中
        paymentRecord.setStatus(HuiFuPayStatusEnums.pending.getCode());
        paymentRecord.setVersion(0);
        paymentRecord.setPayType(param.getPayBizType().name());
        // save db
        ddwxPaymentRecordService.save(paymentRecord);

        // message db
        DdwxPaymentMessageInfoDTO msgInfo = new DdwxPaymentMessageInfoDTO();
        msgInfo.setBizCode(param.getBizCode());
        msgInfo.setEventType(param.getPayBizType().getEventType().name());
        msgInfo.setPayOrderNum(payOrderNum);
        msgInfo.setPushStatus(HuiFuPayStatusEnums.pending.getCode());
        msgInfo.setStatus(HuiFuPayStatusEnums.pending.getCode());
        msgInfo.setNotifyUrl(param.getNotifyUrl());
        msgInfo.setRequestBody(JsonUtils.toJson(payInfo.getRequestParams()));
        msgInfo.setResponseMsg(JsonUtils.toJson(payInfo));
        msgInfo.setPlatform(PayPlatformEnums.HUIFU_ADAPAY.name());
        saveMessage(msgInfo);
    }



    @Override
    public String payBack(HttpServletRequest request) {
        return null;
    }

    /**
     * 根据第三方平台的支付订单号查询第三方平台的支付对象信息
     *
     * @param payDto
     * @return 注：可以切成开发平台 ddwx_payment_record 获取下信息，先暂时取第三方平台SDK接口
     * {
     * "id": "002112020012010545810065165317376983040",
     * "order_no": "123456789",
     * "pay_amt": "0.05",
     * "pay_channel": "alipay",
     * "status": "succeeded"
     * }
     */
    @Override
    public Map<String, Object> infoByPaymentId(PaymentIdDTO payDto) {

        return huiFuPayService.infoByPaymentId(new HuiFuPayConfigStorage
                (payDto.getApiKey(), payDto.getKeyPrivate()), payDto.getPaymentId());
    }

    @Override
    public Result<MemberUserResponse> createPersonalUser(HuiFuMemberUserDTO param) {
        // 转换DTO
        MemberUser memberUser = InstanceConvertUtil.convertObject(param, MemberUser.class);
        if (Objects.nonNull(param.getGender())) {
            memberUser.setGender(param.getGender().name());
        }
        memberUser.setCertType(param.getCertType().getCode());
        // 生成会员id
        memberUser.setMemberId(Constants.HUIFU_MEMBER_PERSONAL_PREFIX + getRandomNum(6, (x) -> ddwxPersonalMemberInfoService.existsByMemberId(x)));
        // 调用汇付天下 adapay SDK
        MemberUserResponse memberUserResponse = huiFuPayService.createPersonalUser
                (new HuiFuPayConfigStorage(param.getApiKey(), param.getKeyPrivate()), memberUser);
        memberUserResponse.setMid(param.getMid());
        memberUserResponse.setNickname(param.getNickname());

        if (HuiFuPayStatusEnums.succeeded.name().equalsIgnoreCase(memberUserResponse.getStatus())) {
            DdwxPersonalMemberInfo memberUserInfo = InstanceConvertUtil.convertObject(memberUserResponse, DdwxPersonalMemberInfo.class);
            memberUserInfo.setCreatedTime(Long.valueOf(memberUserResponse.getCreatedTime()));
            // 持久化DB
            ddwxPersonalMemberInfoService.save(memberUserInfo);
            return Result.success(memberUserResponse);
        } else {
            return Result.fail(ApiCode.HUIFU_USER_PERSON_CREATE_FAIL, memberUserResponse.getErrorMsg());
        }
    }

    @Override
    public Result<MemberUserResponse> queryPersonalUser(HuiFuQueryMemberUserDTO param) {

        return Result.success(huiFuPayService.queryPersonalUser
                (new HuiFuPayConfigStorage(param.getApiKey(), param.getKeyPrivate()),
                        InstanceConvertUtil.convertObject(param, QueryMemberUser.class)));
    }

    @Override
    public Result<List<MemberUserResponse>> listPersonalUser(HuiFuQueryMemberUserDTO param) {
        MemberListData listData = huiFuPayService.listPersonalUser
                (new HuiFuPayConfigStorage(param.getApiKey(), param.getKeyPrivate()),
                        InstanceConvertUtil.convertObject(param, QueryMemberUser.class));
        if (HuiFuPayStatusEnums.failed.name().equalsIgnoreCase(listData.getStatus())) {
            return Result.fail(ApiCode.HUIFU_USER_PERSON_LIST_FAIL, listData.getErrorMsg());
        }
        return Result.success(InstanceConvertUtil.convertList(listData.getMembers(), MemberUserResponse.class));

    }

    @Override
    public Result<CorpMemberUserResponse> createCorpMember(HuiFuCorpMemberUserDTO param) {
        // 校验数据
        checkData(param);
        CorpMemberUser corpMemberUser = InstanceConvertUtil.convertObject(param, CorpMemberUser.class);
        // 本地落地文件并生成文件对象
        corpMemberUser.setAttachFile(getFile(param.getAttachFile(),param.getMid()));
        // app_id 下生成订单编号
        corpMemberUser.setMemberOrderNum(OrderIdUtils.getOrderId());
        if (Objects.nonNull(param.getBankAcctType())) {
            corpMemberUser.setBankAcctType(param.getBankAcctType().getCode() + "");
        }
        // app_id 下生成会唯一 member_id
        corpMemberUser.setMemberId(Constants.HUIFU_CORP_MEMBER_PERSONAL_PREFIX + getRandomNum(6, (x) -> ddwxCorpMemberInfoService.existsByMemberId(x)));
        CorpMemberUserResponse response = huiFuPayService.createCorpMember
                (new HuiFuPayConfigStorage(param.getApiKey(), param.getKeyPrivate()),corpMemberUser);
        // 回传设置
        response.setMid(param.getMid());
        if (HuiFuPayStatusEnums.failed.name().equalsIgnoreCase(response.getStatus())) {
            return Result.fail(ApiCode.HUIFU_USER_PERSON_LIST_FAIL, response.getErrorMsg());
        }
        // 存DB
        saveCorpMemberInfo(response,corpMemberUser);
        return Result.success(response);
    }

    @Transactional(rollbackFor = {Exception.class})
    public void saveCorpMemberInfo(CorpMemberUserResponse response, CorpMemberUser corpUser) {
        DdwxCorpMemberInfo memberInfo =  InstanceConvertUtil.convertObject(corpUser, DdwxCorpMemberInfo.class);
        memberInfo.setAttachFileUrl(corpUser.getAttachFile().getAbsolutePath());
        memberInfo.setCreatedTime(Long.valueOf(response.getCreatedTime()));
        memberInfo.setStatus(HuiFuPayStatusEnums.of(response.getStatus()).getCode());
        ddwxCorpMemberInfoService.save(memberInfo);
    }

    private File getFile(MultipartFile file,String mid) {
        long fileSize = file.getSize(); // 获取文件大小，单位为字节
        if (fileSize == 0){
            throw new CustomException(ApiCode.HUIFU_USER_CORP_CREATE_FAIL,"文件不能为空");
        }
        if (fileSize > 9 * 1024 * 1024){
            throw new CustomException(ApiCode.HUIFU_USER_CORP_CREATE_FAIL,"内容须包含三证合一证件照、法人身份证正面照、法人身份证反面照、开户银行许可证照。 压缩 zip包后上传，最大限制为 9 M");
        }
        try {
            // 保存文件到本地目录
            byte[] bytes = file.getBytes();
            File dest = new File(filePath +mid+"/"+System.currentTimeMillis()+"/" + file.getOriginalFilename());
            if (!dest.getParentFile().exists()){
                dest.getParentFile().mkdirs();
            }
            FileOutputStream fos = new FileOutputStream(dest);
            fos.write(bytes);
            fos.close();
            return dest;
        }catch (Exception e){
            e.printStackTrace();
            throw new CustomException(ApiCode.HUIFU_USER_CORP_CREATE_FAIL,"文件保存失败");
        }
    }

    private void checkData(HuiFuCorpMemberUserDTO param) {

        // 银行账户类型：1-对公；2-对私，如果需要自动开结算账户，本字段必填
        if (Objects.isNull(param.getBankAcctType())) {
            return;
        }
        // 银行代码，如果需要自动开结算账户，本字段必填（详见附录 银行代码）
        if (StringUtils.isBlank(param.getBankCode())){
            throw new CustomException(ApiCode.HUIFU_USER_CORP_CREATE_FAIL,"银行代码不能为空，涉及自动开结算账户");
        }
        // 银行卡号，如果需要自动开结算账户，本字段必填
        if (StringUtils.isBlank(param.getCardNo())){
            throw new CustomException(ApiCode.HUIFU_USER_CORP_CREATE_FAIL,"银行卡号不能为空，涉及自动开结算账户");
        }
        // 银行卡对应的户名，如果需要自动开结算账户，本字段必填；若银行账户类型是对公，必须与企业名称一致
        if (StringUtils.isBlank(param.getCardName())){
            throw new CustomException(ApiCode.HUIFU_USER_CORP_CREATE_FAIL,"银行卡对应的户名不能为空，涉及自动开结算账户");
        }
    }
}
